home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / scopedisk24 / Qrt14src / ray.c < prev    next >
C/C++ Source or Header  |  1988-08-23  |  19KB  |  771 lines

  1. /************************************************************
  2.  
  3.                      ray trace module
  4.  
  5.  ************************************************************/
  6.  
  7. #include <math.h>
  8. #include "qrt.h"
  9.  
  10. /* #define RAYDEBUG 1 */
  11.  
  12. OBJ_PTR new_line(), new_obj();
  13.  
  14.  
  15. /**********************************************************
  16.  
  17.   Diffuse color module. Also compute specular reflections
  18.   here for efficiency sake - only one lamp eneumerator
  19.   needed that way.
  20.  
  21.  **********************************************************/
  22.  
  23. DiffColor(color,cinfo,norm,loc,oline)
  24.   SVECT_PTR color;
  25.   VECT_PTR norm,loc;
  26.   CINFO_PTR cinfo;
  27.   OBJ_PTR oline;
  28. {
  29.   OBJ_PTR lamp, line, CurrObj, Ray_Hit();
  30.   float t;
  31.   register float dist, t1,t2;
  32.   VECTOR refl, atten;
  33.  
  34.   line=new_line();
  35.   VectEQ(&(line->loc),loc);
  36.   lamp=THEWORLD.lamps;
  37.  
  38.   while (lamp!=NULL) {
  39.  
  40. #   ifdef ROBUST
  41.       if (lamp->type!=LAMP) Error(INTERNAL_ERROR,601);
  42. #   endif
  43.  
  44.     /* find dir to lamp */
  45.     VecSubtract(&(line->vect1),&(lamp->loc),loc);
  46.  
  47.     CurrObj=NULL;
  48.     atten.x = atten.y = atten.z = 1.00;
  49.  
  50.     if (def.shadow==TRUE) {
  51.  
  52.       /* set light attenuation factor */
  53.  
  54.       CurrObj=Ray_Hit(THEWORLD.stack,line,&t,TRUE,TRUE,&atten);
  55.  
  56.       THEWORLD.to_lamp++;
  57.     }
  58.  
  59.     if (CurrObj==NULL) {                         /* hit nothing ? */
  60.  
  61.       dist = DotProd((line->vect1),(line->vect1));
  62.       Normalize(&(line->vect1));
  63.  
  64.       if (cinfo->diff.r>0 || cinfo->diff.g>0 || cinfo->diff.b>0) {
  65.         t1 = DotProd((*norm),(line->vect1));
  66.  
  67.         if (t1>0) {
  68.           t2 = lamp->vect1.y*t1/sqrt(dist);
  69.  
  70.           color->r+=(short)((lamp->cinfo.amb.r) * atten.x *
  71.                     t2*(cinfo->diff.r)/CNUM);
  72.           color->g+=(short)((lamp->cinfo.amb.g) * atten.y *
  73.                     t2*(cinfo->diff.g)/CNUM);
  74.           color->b+=(short)((lamp->cinfo.amb.b) * atten.z *
  75.                     t2*(cinfo->diff.b)/CNUM);
  76.         }
  77.       }
  78.  
  79.       if (cinfo->sreflect>0) {                 /* specular */
  80.         line->vect1.x = -line->vect1.x;        /* reverse line */
  81.         line->vect1.y = -line->vect1.y;
  82.         line->vect1.z = -line->vect1.z;
  83.         Reflect(&refl,&(line->vect1),norm);
  84.         t1 = -DotProd(refl,(oline->vect1));
  85.         if (t1>0) {
  86.  
  87.           t2 = pow(t1,cinfo->sreflect)*        /* this is slow !! */
  88.                lamp->vect1.y/sqrt(dist);
  89.  
  90.           t2 *= (float)cinfo->reflect/(float)CNUM;
  91.  
  92.           color->r+=(short)(t2 * atten.x * (lamp->cinfo.amb.r));
  93.           color->g+=(short)(t2 * atten.y * (lamp->cinfo.amb.g));
  94.           color->b+=(short)(t2 * atten.z * (lamp->cinfo.amb.b));
  95.         }
  96.       }
  97.     }
  98.     lamp=lamp->nextobj;
  99.   }
  100.  
  101. # ifdef RAYDEBUG
  102.     printf("DIFFCOLOR: r=%d, g=%d, b=%d\n",
  103.             color->r, color->g, color->b);
  104. # endif
  105.  
  106.   free(line);
  107. }
  108.  
  109.  
  110. /**********************************************************
  111.  
  112.                      Ambient color module
  113.  
  114.    Really simple - just add the color, no questions asked.
  115.  
  116.  **********************************************************/
  117.  
  118. AmbColor(color, cinfo, norm, loc)
  119.   SVECT_PTR color;
  120.   VECT_PTR norm, loc;
  121.   CINFO_PTR cinfo;
  122. {
  123.   color->r+=(short)((int)cinfo->amb.r*(int)cinfo->diff.r/CNUM);
  124.   color->g+=(short)((int)cinfo->amb.g*(int)cinfo->diff.g/CNUM);
  125.   color->b+=(short)((int)cinfo->amb.b*(int)cinfo->diff.b/CNUM);
  126.  
  127. # ifdef RAYDEBUG
  128.     printf("AMBCOLOR: added r=%d, g=%d, b=%d\n",
  129.             cinfo->amb.r,cinfo->amb.g,cinfo->amb.b);
  130. # endif
  131. }
  132.  
  133.  
  134. /**********************************************************
  135.  
  136.                  Transmitted color module
  137.  
  138.  This is hairy and slow - bends ray around normal vector
  139.  by ratio of indicies of refraction.  line->flag=TRUE
  140.  if we are inside a piece of glass - this means glass must
  141.  have a simple structure.
  142.  
  143.  10 Aug 88 - Fixed TransColor so that it works.  The
  144.  original algorithm came from a book, and I had some
  145.  problems getting it to work.  This one came from my head,
  146.  and seems to work ok.
  147.  
  148.  11 Aug 88 - Added density effects (light is reduced
  149.  more by thicker glass).
  150.  
  151.  **********************************************************/
  152.  
  153. /* #define TESTTRANS TRUE */
  154.  
  155. TransColor(color,cinfo,norm,loc,line,inmult)
  156.   SVECT_PTR color;
  157.   VECT_PTR norm,loc;
  158.   OBJ_PTR line;
  159.   CINFO_PTR cinfo;
  160.   float inmult;
  161. {
  162.   OBJ_STRUCT newline;
  163.   SVECTOR    col1;
  164.   VECTOR     toadd, negvect1, distance;
  165.   float      index2, multiplier, side1;
  166.   int        maxtrans;
  167.  
  168.   /* these vars are used to keep track of the distance
  169.      traveled through the glass so we can attenuate the
  170.      light accordingly.                                 */
  171.  
  172.   static     VECTOR prevpos;
  173.   VECTOR     displacement;
  174.   SVECTOR    attenuation;
  175.   float      glassdist;
  176.  
  177. # ifdef TRANSDEBUG
  178.     printf("TRANSCOLOR:\n");
  179. # endif
  180. # ifdef RAYDEBUG
  181.     printf("TRANSCOLOR:\n");
  182. # endif
  183.  
  184.   if ((cinfo->trans.r < def.ithreshold) &&
  185.       (cinfo->trans.g < def.ithreshold) &&
  186.       (cinfo->trans.b < def.ithreshold)) return;
  187.  
  188. # ifdef ROBUST
  189.     if (line->type!=LINE) Error(INTERNAL_ERROR,602);
  190.     if ((THEWORLD.globindex == 0) ||
  191.         (cinfo->index == 0))
  192.           Error(ZERO_INDEX,603);
  193. # endif
  194.  
  195.   if (line->flag) {
  196.  
  197.     /* inside an object going out ? */
  198.     index2 = cinfo->index/THEWORLD.globindex;
  199.  
  200.     /* find offset from prev position */
  201.     VecSubtract(&displacement,loc,&prevpos);
  202.  
  203.     /* measure distance */
  204.     glassdist = sqrt(DotProd(displacement,displacement));
  205.  
  206.   } else {
  207.  
  208.     /* outside an object going in ? */
  209.     index2 = THEWORLD.globindex/cinfo->index;
  210.     /* remember this position */
  211.     VectEQ(&prevpos,loc);
  212.   }
  213.  
  214.   /* doesn't currently use new_line() call */
  215.   newline.type = LINE;
  216.   newline.child = newline.nextobj = NULL;
  217.  
  218.   /* this ray starts from where we hit glass */
  219.   VectEQ(&(newline.loc),loc);
  220.   VectEqZero(&toadd);
  221.  
  222.   VectNegate(&negvect1,&(line->vect1));
  223.   side1 = DotProd((*norm),negvect1);
  224.  
  225.   VectAddMult(&toadd,-side1,norm,(float)1,&negvect1);
  226.  
  227.   VectScale(&toadd,(1-index2));
  228.  
  229.   VectorAdd(&(newline.vect1),&(line->vect1),&toadd);
  230.  
  231.   Normalize(&(newline.vect1));
  232.  
  233.   maxtrans = MAX(MAX(cinfo->trans.r,cinfo->trans.g),
  234.                      cinfo->trans.b);
  235.  
  236.   /* if we were inside, now we're out */
  237.   newline.flag = !(line->flag);
  238.  
  239. # ifdef TESTTRANS
  240.  
  241.     if (line->flag) printf("line TRUE\n");
  242.     if (newline.flag) printf("newline TRUE\n");
  243.  
  244.     printf("Trans = %d %d %d\n",cinfo->trans.r,
  245.                                 cinfo->trans.g,
  246.                                 cinfo->trans.b);
  247.  
  248.     printf("index2 = %f\n",index2);
  249.     printf("side1  = %f\n",side1);
  250.  
  251.     printf("Dot(toadd,norm) = %f\n",
  252.            DotProd(toadd,(*norm)));
  253.  
  254.     printf("Dot(norm,negvect1) = %f\n",
  255.            DotProd((*norm),negvect1));
  256.  
  257.     printf("Dot(-norm,newvect) = %f\n",
  258.            -DotProd((*norm),newline.vect1));
  259.  
  260.     printf("inmult, maxtrans = %f %d\n",inmult,maxtrans);
  261. # endif
  262.  
  263.   multiplier = inmult * (float)maxtrans/(float)CNUM;
  264.   Ray_Trace(&newline,&col1,multiplier);
  265.   THEWORLD.refl_trans++;
  266.  
  267. # ifdef TESTTRANS
  268.     printf("Col1 = %d %d %d\n",col1.r,col1.g,col1.b);
  269. # endif
  270.  
  271.   color->r += col1.r;
  272.  
  273.   color->g += col1.g;
  274.  
  275.   color->b += col1.b;
  276.  
  277.   if (line->flag) {          /* density effects? */
  278.  
  279.     /* density uses x,y,z not r,g,b cuz its a floating
  280.        point vector.                                   */
  281.  
  282.     attenuation.r = (int)(cinfo->density.x * glassdist *
  283.                          (float)(color->r));
  284.  
  285.     attenuation.g = (int)(cinfo->density.y * glassdist *
  286.                          (float)(color->g));
  287.  
  288.     attenuation.b = (int)(cinfo->density.z * glassdist *
  289.                          (float)(color->b));
  290.  
  291.     /* don't remove more than original intensity! */
  292.  
  293.     color->r -= MIN(attenuation.r,color->r);
  294.     color->g -= MIN(attenuation.g,color->g);
  295.     color->b -= MIN(attenuation.b,color->b);
  296.  
  297.   }
  298. }
  299.  
  300.  
  301. /**********************************************************
  302.  
  303.                    Reflective color module
  304.  
  305.       Bounce ray off object and recursively ray trace.
  306.  
  307.  **********************************************************/
  308.  
  309. ReflectColor(color,cinfo,norm,loc,line,inmult)
  310.   SVECT_PTR color;
  311.   VECT_PTR  norm,loc;
  312.   OBJ_PTR   line;
  313.   CINFO_PTR cinfo;
  314.   float inmult;
  315. {
  316.   SVECTOR col1;
  317.   OBJ_STRUCT newline;
  318.   float multiplier;
  319.   int maxmirror;
  320.  
  321. # ifdef ROBUST
  322.     if (line->type!=LINE) Error(INTERNAL_ERROR,604);
  323. # endif
  324.  
  325.   if ((cinfo->mirror.r < def.ithreshold) &&
  326.       (cinfo->mirror.g < def.ithreshold) &&
  327.       (cinfo->mirror.b < def.ithreshold)) return;
  328.  
  329.   newline.type = LINE;
  330.  
  331.   newline.child = newline.nextobj = NULL;
  332.  
  333.   VectEQ(&(newline.loc),loc);
  334.   Reflect(&(newline.vect1),&(line->vect1),norm);
  335.  
  336.   maxmirror = MAX(MAX(cinfo->mirror.r,cinfo->mirror.g),
  337.               cinfo->mirror.b);
  338.  
  339.   multiplier = inmult * (float)maxmirror/CNUM;
  340.  
  341.   Ray_Trace(&newline,&col1,multiplier);
  342.   THEWORLD.refl_trans++;
  343.  
  344.   color->r+=(int)col1.r*(int)cinfo->mirror.r/CNUM;
  345.  
  346.   color->g+=(int)col1.g*(int)cinfo->mirror.g/CNUM;
  347.  
  348.   color->b+=(int)col1.b*(int)cinfo->mirror.b/CNUM;
  349.  
  350. # ifdef RAYDEBUG
  351.     printf("REFLECTCOLOR:\n");
  352.     printf("  col1 = %d %d %d\n",col1.r,col1.g,col1.b);
  353. # endif
  354.  
  355. }
  356.  
  357.  
  358. /**********************************************************
  359.  
  360.    Computes sky color given line - interpolate between
  361.    horizon and zenith to find color (user should dither
  362.    the explitive out of the sky to compensate for lack
  363.    of color resolution.
  364.  
  365.  **********************************************************/
  366.  
  367. SkyColor(line,color)
  368.   OBJ_PTR line;
  369.   SVECT_PTR color;
  370. {
  371.   float length, horiz, zenith;
  372.  
  373. # ifdef ROBUST
  374.     if (line->type!=LINE) Error(INTERNAL_ERROR,605);
  375. # endif
  376.  
  377.   if (THEWORLD.sky==NULL) return;
  378.  
  379. # ifdef ROBUST
  380.     if (THEWORLD.sky->type != SKY)
  381.       Error(INTERNAL_ERROR,606);
  382. # endif
  383.  
  384.   length = DotProd(line->vect1,line->vect1);
  385.  
  386.   zenith = sqr(line->vect1.y)/length;
  387.   horiz  = (sqr(line->vect1.x)+sqr(line->vect1.z))/length;
  388.  
  389.   color->r += (short)(zenith*THEWORLD.skycolor_zenith.r+
  390.                       horiz *THEWORLD.skycolor_horiz.r);
  391.  
  392.   color->g += (short)(zenith*THEWORLD.skycolor_zenith.g+
  393.                       horiz *THEWORLD.skycolor_horiz.g);
  394.  
  395.   color->b += (short)(zenith*THEWORLD.skycolor_zenith.b+
  396.                       horiz *THEWORLD.skycolor_horiz.b);
  397.  
  398.   Dither(color,&((THEWORLD.sky)->cinfo));
  399.  
  400.  
  401. # ifdef RAYDEBUG
  402.     printf("SKYCOLOR:\n");
  403. # endif
  404.  
  405. }
  406.  
  407.  
  408. /**********************************************************
  409.  
  410.   Color dithering rountine - negative dither number will
  411.   dither all three colors together - positive with perform
  412.   separate color dithering on all colors.
  413.  
  414.  **********************************************************/
  415.  
  416. #define MINCOL 10
  417. Dither(color,cinfo)
  418.   SVECT_PTR color;
  419.   CINFO_PTR cinfo;
  420. {
  421.   register int r,g,b;
  422.   int PsRand();
  423.  
  424.   if (cinfo->dither==0) return;
  425.  
  426.   if (cinfo->dither>0) {
  427.     r=PsRand(); g=PsRand(); b=PsRand();
  428.  
  429.     if (color->r<MINCOL) r=IABS(r);
  430.     if (color->g<MINCOL) g=IABS(g);
  431.     if (color->b<MINCOL) b=IABS(b);
  432.  
  433.     color->r += (short)(r*cinfo->dither/CNUM);
  434.     color->g += (short)(g*cinfo->dither/CNUM);
  435.     color->b += (short)(b*cinfo->dither/CNUM);
  436.   } else {
  437.     r=PsRand();
  438.     if ((color->r+color->g+color->b)>(3*MINCOL)) r=IABS(r);
  439.  
  440.     color->r += (short)(r*cinfo->dither/CNUM);
  441.     color->g += (short)(r*cinfo->dither/CNUM);
  442.     color->b += (short)(r*cinfo->dither/CNUM);
  443.   }
  444. }
  445.  
  446.  
  447. /**********************************************************
  448.  
  449.    Returns pointer to object hit by ray.
  450.    Parameters:
  451.      CurrObj = root of object tree
  452.      line    = light ray
  453.      MinT    = parameter T for line/obj intersection
  454.      sflag   = if TRUE, stop on first intersection
  455.      fflag   = ALWAYS pass TRUE here.
  456.      pos1    = position vector for object relative coords
  457.      pos2    = position vector for object relative coords
  458.  
  459.   - changed 11 jun 88 to fix shadow routine -
  460.  
  461.   - changed 12 aug 88 to add light attenuation by glass.
  462.             this is not done correctly, but is better
  463.             than nothing.
  464.  
  465.  **********************************************************/
  466.  
  467. OBJ_PTR Ray_Hit(CurrObj,line,MinT,sflag,fflag,atten)
  468.   OBJ_PTR line, CurrObj;
  469.   float *MinT;
  470.   short sflag,fflag;
  471.   VECT_PTR atten;           /* light attenuation by glass */
  472. {
  473.   static OBJ_PTR MinObj;
  474.   VECTOR loc;
  475.   OBJ_PTR obj;
  476.   short collision;
  477.   static short stop;
  478.   float t;
  479.  
  480.   obj = CurrObj;
  481.  
  482.   if (fflag) {
  483.  
  484. #   ifdef ROBUST
  485.       if (line->type!=LINE) Error(INTERNAL_ERROR,607);
  486. #   endif
  487.  
  488.     *MinT=3e30;
  489.     MinObj=NULL;
  490.     stop=FALSE;
  491.   }
  492.  
  493.   while (obj!=NULL && !stop) {         /* check for object collisions */
  494.  
  495.     collision =
  496.       (*(ObjData[obj->type].ColTest))(line,obj,&t);
  497.  
  498.     if (collision && (obj->remove != NULL)) {
  499.       FindPos(&loc,line,t);
  500.       if (Find_Color(obj,obj->remove,&loc,NULL, 1.0, 1.0))
  501.         collision = FALSE;
  502.     }
  503.  
  504.     THEWORLD.intersect_tests++;
  505.  
  506.     if (collision && (t>SMALL)) {      /* did we hit something ? */
  507.  
  508. #     ifdef RAYDEBUG
  509.         printf("RAY_HIT: Collision t=%f\n",t);
  510. #     endif
  511.  
  512.       if (obj->type!=BBOX) {           /* if not BBOX */
  513.         THEWORLD.ray_intersects++;
  514.         if (sflag && t<1) {
  515.  
  516.           /* did we hit a transparent object? */
  517.           /* PS - this is not right - fix it later */
  518.  
  519.           if ((obj->cinfo.trans.r < def.ithreshold) &&
  520.               (obj->cinfo.trans.g < def.ithreshold) &&
  521.               (obj->cinfo.trans.b < def.ithreshold)) {
  522.  
  523.             stop   = TRUE;
  524.             MinObj = obj;
  525.             return(obj);
  526.  
  527.           } else {
  528.  
  529.             /* attenuate light if transparent object.  This is
  530.                REALLY screwy and not at all correct, but it is
  531.                the only simple way to do it.
  532.             */
  533.  
  534.             if (atten != NULL) {
  535.               atten->x *= sqr(((float)obj->cinfo.trans.r) /
  536.                           (float)CNUM);
  537.               atten->y *= sqr(((float)obj->cinfo.trans.g) /
  538.                           (float)CNUM);
  539.               atten->z *= sqr(((float)obj->cinfo.trans.b) /
  540.                           (float)CNUM);
  541.             }
  542.           }
  543.         }
  544.         if ((!sflag) && (t<*MinT)) {   /* nearest collision ? */
  545.           *MinT  = t;                  /* if so, save it */
  546.           MinObj = obj;
  547.         }
  548.       } else {                         /* is bbox hit */
  549.         THEWORLD.bbox_intersects++;
  550.         Ray_Hit(obj->child,line,MinT,sflag,FALSE,atten);
  551.       }
  552.     }
  553.     obj=obj->nextobj;
  554.   }
  555.  
  556.   return(MinObj);
  557. }
  558.  
  559.  
  560. /**********************************************************
  561.  
  562.   Performs ray tracing in line, fills color structure.
  563.   Multiplier is a number by which the color output will
  564.   be mulplied (0..1) so that we can tell when its useless
  565.   to continue recursivly tracing rays.
  566.  
  567.  **********************************************************/
  568.  
  569. int Ray_Trace(line,color,multiplier)
  570.   OBJ_PTR line;
  571.   SVECT_PTR color;
  572.   float multiplier;
  573. {
  574.   float MinT, divisor;
  575.   OBJ_PTR MinObj;
  576.   CINFO cinfo;
  577.   VECTOR MinLoc, MinNorm;
  578.  
  579. # ifdef ROBUST
  580.     if (line->type!=LINE) Error(INTERNAL_ERROR,608);
  581. # endif
  582.  
  583.   color->r = color->g = color->b = 0;
  584.  
  585.   /* check here if so little light is added that it doesn't matter */
  586.   if (multiplier < def.threshold) return(FALSE);
  587.  
  588.   MinObj=Ray_Hit(THEWORLD.stack,line,&MinT,FALSE,TRUE,NULL);
  589.  
  590.   if (MinObj!=NULL) {
  591.     FindPos(&MinLoc,line,MinT);
  592.  
  593. #   ifdef RAYDEBUG
  594.       printf("RAY_TRACE: Collision, x,y,z = %f %f %f\n",
  595.              MinLoc.x, MinLoc.y, MinLoc.z);
  596. #   endif
  597.  
  598.     /*  Find object normal vector */
  599.  
  600.     (*(ObjData[MinObj->type].FindNorm))(&MinNorm,MinObj,&MinLoc);
  601.  
  602.     if (DotProd(MinNorm,(line->vect1)) >0) {   /* reverse   */
  603.       MinNorm.x = -MinNorm.x;                  /* normal if */
  604.       MinNorm.y = -MinNorm.y;                  /* necessary */
  605.       MinNorm.z = -MinNorm.z;
  606.     }
  607.                                                /* Find colinfo */
  608.     Find_Color(MinObj,
  609.                MinObj->pattern,
  610.                &MinLoc,
  611.                &cinfo,
  612.                MinObj->xmult,
  613.                MinObj->ymult
  614.               );
  615.  
  616.     AmbColor(color,&cinfo,&MinNorm,&MinLoc);
  617.     DiffColor(color,&cinfo,&MinNorm,&MinLoc,line);
  618.     TransColor(color,&cinfo,&MinNorm,&MinLoc,line,multiplier);
  619.     ReflectColor(color,&cinfo,&MinNorm,&MinLoc,line,multiplier);
  620.     Dither(color,&cinfo);
  621.  
  622.   } else {
  623.     SkyColor(line,color);
  624.   }
  625.  
  626.   if (color->r > CNUM || color->g > CNUM || color->b > CNUM) {
  627.     divisor = (float)MAX(MAX(color->r,color->g),color->b) /
  628.               (float)CNUM;
  629.  
  630.     color->r = (float)color->r/divisor;
  631.     color->g = (float)color->g/divisor;
  632.     color->b = (float)color->b/divisor;
  633.   }
  634.  
  635.   return(MinObj!=NULL);
  636. }
  637.  
  638.  
  639. /**********************************************************
  640.  
  641.      Generates line for a given x,y pixel position
  642.      This fn needs a little work, as currently it
  643.      produces some distortion around the edge of
  644.      the screen.
  645.  
  646.  **********************************************************/
  647.  
  648. PixelLine(x, y, line)           /* generate equation for a line */
  649.   int x,y;
  650.   OBJ_PTR line;
  651. {
  652.   register float xf, yf;
  653.  
  654. # ifdef ROBUST
  655.     if (line->type!=LINE) Error(INTERNAL_ERROR,609);
  656. # endif
  657.  
  658.   xf=((float)(CENTERX-x))/(THEWORLD.flength*ASPECT);
  659.   yf=((float)(CENTERY-y))/(THEWORLD.flength);
  660.  
  661.   VectEQ(&(line->loc),&(THEWORLD.observer->loc));
  662.   VectEQ(&(line->vect1),&(THEWORLD.observer->vect1));
  663.   VectAddMult(&(line->vect1),xf,&(THEWORLD.obsright),
  664.                              yf,&(THEWORLD.obsup));
  665.  
  666.   line->flag = FALSE;           /* redundant? */
  667. }
  668.  
  669.  
  670. /**********************************************************
  671.  
  672.                     Not yet implimented
  673.  
  674.  **********************************************************/
  675.  
  676. Region_Trace(xbegin,xend,ybegin,yend)
  677.   int xbegin, xend, ybegin, yend;
  678. {
  679.   int x,y;
  680. }
  681.  
  682.  
  683. /**********************************************************
  684.  
  685.    Sends scan line color data to file - file format is:
  686.  
  687.    BYTE 0 : low  byte of x resolution
  688.    BYTE 1 : high byte of x resolution
  689.    BYTE 2 : low  byte of y resolution
  690.    BYTE 3 : high byte of y resolution
  691.  
  692.    Then, for each scan line, the line number is listed
  693.    (2 bytes), followed by the r,g, and b bytes.
  694.  
  695.  **********************************************************/
  696.  
  697. Dump_Line(lineno,r,g,b)
  698.   short r[],g[],b[];
  699.   int lineno;
  700. {
  701.   int x;
  702.  
  703. #ifndef RAYDEBUG
  704.  
  705.   /** line number **/
  706.  
  707.   fputc(((unsigned char)(lineno&(0xff))),THEWORLD.filept);
  708.   fputc(((unsigned char)(lineno>>8)),    THEWORLD.filept);
  709.  
  710.   for (x=0; x<XSIZE; x++) {
  711.     fputc((unsigned char)r[x],THEWORLD.filept);
  712.   }
  713.   for (x=0; x<XSIZE; x++) {
  714.     fputc((unsigned char)g[x],THEWORLD.filept);
  715.   }
  716.   for (x=0; x<XSIZE; x++) {
  717.     fputc((unsigned char)b[x],THEWORLD.filept);
  718.   }
  719. #endif
  720. }
  721.  
  722.  
  723. /**********************************************************
  724.  
  725.                   Ray trace whole screen
  726.  
  727.  **********************************************************/
  728.  
  729. Screen_Trace() {
  730.   int x,y;
  731.   short rbyte[XSIZE], gbyte[XSIZE], bbyte[XSIZE];
  732.   SVECTOR color;
  733.   OBJ_PTR line;
  734.  
  735.   line=new_line();
  736.  
  737. # ifdef RAYDEBUG
  738.     printf("SCREEN_TRACE: line:\n");
  739.     printf("First,Last = %d %d\n",
  740.            THEWORLD.first_scan,THEWORLD.last_scan);
  741. # endif
  742.  
  743.   for (y=THEWORLD.first_scan; y<=THEWORLD.last_scan; y++) {
  744.  
  745.     for (x=0; x<XSIZE; x++) {
  746.  
  747.       PixelLine(x,y,line);
  748.  
  749.       Ray_Trace(line,&color,(float)1.0);
  750.       THEWORLD.primary_traced++;
  751.  
  752. #     ifdef RAYDEBUG
  753.         printf("SCREEN_TRACE: r,g,b = %d %d %d\n",
  754.                color.r,color.g,color.b);
  755. #     endif
  756.  
  757.       rbyte[x] = color.r;
  758.       gbyte[x] = color.g;
  759.       bbyte[x] = color.b;
  760.  
  761. #     ifdef RAYDEBUG
  762.         printf("SCREEN_TRACE: r=%d, g=%d, b=%d\n",
  763.                color.r,color.g,color.b);
  764. #     endif
  765.     }
  766.  
  767.     Dump_Line(y,rbyte,gbyte,bbyte);
  768.   }
  769.   free(line);
  770. }
  771.